﻿using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Collections;
using Microsoft.SqlServer.Server;


[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = -1)]
public class Median : IBinarySerialize
{
    private ArrayList valueList;
    private int middle;

    public void Init()
    {
        this.valueList = new ArrayList();
    }

    public void Accumulate(SqlDouble Value)
    {
        if (Value.IsNull)
        {
            return;
        }

        this.valueList.Add(Value);
    }

    public void Merge(Median Group)
    {
        this.valueList.AddRange(Group.valueList);
    }

    public SqlDouble Terminate()
    {
        this.valueList.Sort();
        if (this.valueList.Count % 2 == 0)
        {
            middle = (this.valueList.Count / 2);
            return (Convert.ToDouble(this.valueList[middle - 1]) +
            Convert.ToDouble(this.valueList[middle])) / 2.0;
        }
        else
        {
            middle = (this.valueList.Count + 1) / 2;
            return Convert.ToDouble(this.valueList[middle - 1]);
        }
    }

    public void Read(BinaryReader r)
    {
        valueList = new ArrayList();
        string[] tmpList = r.ReadString().Split('|');
        foreach (string entry in tmpList)
        {
            valueList.Add(Convert.ToDouble(entry));
        }
    }

    public void Write(BinaryWriter w)
    {
        string[] tmpList = new string[valueList.Count];
        for (int i = 0; i < valueList.Count; i++)
        {
            tmpList[i] = Convert.ToString(valueList[i]);
        }
        w.Write(String.Join("|", tmpList));
    }
}